using AutoMapper;
using B.S.XZYData.Api.Read.Application.Command.WorkOrderReport;
using B.S.XZYData.Domain.LJC;
using B.S.XZYData.Domain.LJC.Dto;
using B.S.XZYData.Domain.ZSH;
using B.S.XZYData.ErrorCode;
using B.S.XZYData.Infrastructure.Interface;
using MediatR;
using Microsoft.Extensions.Logging;
using SqlSugar;
using System.Linq;

namespace B.S.XZYData.Api.Read.Application.Handler.WorkOrderReport
{
    /// <summary>
    /// 获取工单报工关联列表处理器
    /// </summary>
    public class GetWorkOrderReportListHandler : IRequestHandler<GetWorkOrderReportListCommand, ApiPageing<WorkOrderReportViewDto>>
    {
        private readonly IBaseRepository<WorkOrderModel> _workOrderRepo;
        private readonly IBaseRepository<Domain.ZSH.WorkReport> _workReportRepo;
        private readonly IBaseRepository<WorkOrderReportRelationModel> _relationRepo;
        private readonly IBaseRepository<WorkOrderProcessModel> _workOrderProcessRepo;
        private readonly IMapper _mapper;
        private readonly ILogger<GetWorkOrderReportListHandler> _logger;

        public GetWorkOrderReportListHandler(
            IBaseRepository<WorkOrderModel> workOrderRepo,
            IBaseRepository<Domain.ZSH.WorkReport> workReportRepo,
            IBaseRepository<WorkOrderReportRelationModel> relationRepo,
            IBaseRepository<WorkOrderProcessModel> workOrderProcessRepo,
            IMapper mapper,
            ILogger<GetWorkOrderReportListHandler> logger)
        {
            _workOrderRepo = workOrderRepo;
            _workReportRepo = workReportRepo;
            _relationRepo = relationRepo;
            _workOrderProcessRepo = workOrderProcessRepo;
            _mapper = mapper;
            _logger = logger;
        }

        public async Task<ApiPageing<WorkOrderReportViewDto>> Handle(GetWorkOrderReportListCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation($"开始查询工单报工关联列表（通过中间表），页码：{request.Index}，每页大小：{request.Size}");

                // 构建中间表查询 - 只查询未删除的关联关系
                var relationQuery = _relationRepo.GetAll()
                    .Where(rel => !rel.IsDeleted);

                // 应用中间表筛选条件
                if (request.CreateStartDate.HasValue)
                {
                    relationQuery = relationQuery.Where(rel => rel.CreateTime >= request.CreateStartDate.Value);
                }

                if (request.CreateEndDate.HasValue)
                {
                    relationQuery = relationQuery.Where(rel => rel.CreateTime <= request.CreateEndDate.Value.AddDays(1));
                }

                // CreateBy筛选条件移到后面，在内存中根据报工表的Producer字段筛选

                // 通过中间表关联工单和报工表
                // 工单表通过WorkOrderId关联，报工表通过WorkOrderCode关联
                var joinQueryData = await relationQuery
                    .LeftJoin(_workOrderRepo.GetAll(), (rel, wo) => rel.WorkOrderId == wo.Id)
                    .LeftJoin(_workReportRepo.GetAll(), (rel, wo, wr) => wo.Code == wr.WorkOrderCode)
                    .Select((rel, wo, wr) => new
                    {
                        // 中间表信息
                        RelationId = rel.Id,
                        RelationType = rel.RelationType,
                        RelationRemark = rel.Remark,
                        RelationCreateTime = rel.CreateTime,
                        RelationCreateBy = rel.CreateBy,
                        RelationUpdateBy = rel.UpdateBy,
                        RelationUpdateTime = rel.UpdateTime,
                        
                        // 工单信息
                        WorkOrderId = wo.Id,
                        WorkOrderCode = wo.Code,
                        WorkOrderProductCode = wo.ProductCode,
                        WorkOrderProductName = wo.ProductName,
                        WorkOrderUnit = wo.Unit,
                        WorkOrderStatus = wo.Status,
                        PlannedStartTime = wo.PlannedStartTime,
                        PlannedEndTime = wo.PlannedEndTime,
                        PlannedQuantity = wo.PlannedQuantity,
                        ActualQuantity = wo.ActualQuantity,
                        WorkOrderGoodQuantity = wo.GoodQuantity,
                        WorkOrderBadQuantity = wo.BadQuantity,
                        WorkOrderRemark = wo.Remark,
                        WorkOrderCreateBy = wo.CreateBy,
                        WorkOrderCreateTime = (DateTime?)wo.CreateTime,
                        WorkOrderUpdateBy = wo.UpdateBy,
                        WorkOrderUpdateTime = wo.UpdateTime,
                        
                        // 报工信息 (使用nullable类型 - ZSH.WorkReport字段)
                        WorkReportId = (int?)wr.Id,
                        WorkReportProcessName = wr.ProcessName,
                        WorkReportProductCode = wr.ProductCode,
                        WorkReportProductNo = wr.ProductNo,
                        WorkReportProductName = wr.ProductName,
                        WorkReportProductSpec = wr.ProductSpec,
                        WorkReportReportQty = wr.ReportQty,
                        WorkReportProducer = wr.Producer,
                        WorkReportUnit = wr.Unit,
                        WorkReportGoodQty = (int?)wr.GoodQty,
                        WorkReportDefectiveQty = (int?)wr.DefectiveQty,
                        ReportHours = (decimal?)wr.ReportHours,
                        ProcessProgress = wr.ProcessProgress,
                        WorkReportCreateTime = (DateTime?)wr.CreateTime,
                        WorkReportCreatorId = wr.CreatorId
                    })
                    .ToListAsync();

                // 应用工单筛选条件（在内存中过滤）
                if (!string.IsNullOrEmpty(request.WorkOrderCode))
                {
                    joinQueryData = joinQueryData.Where(x => x.WorkOrderCode != null && x.WorkOrderCode.Contains(request.WorkOrderCode)).ToList();
                }
                
                if (!string.IsNullOrEmpty(request.ProductCode))
                {
                    joinQueryData = joinQueryData.Where(x => 
                        (x.WorkReportProductCode != null && x.WorkReportProductCode.Contains(request.ProductCode)) ||
                        (x.WorkOrderProductCode != null && x.WorkOrderProductCode.Contains(request.ProductCode))).ToList();
                }
                
                if (!string.IsNullOrEmpty(request.ProductName))
                {
                    joinQueryData = joinQueryData.Where(x => 
                        (x.WorkReportProductName != null && x.WorkReportProductName.Contains(request.ProductName)) ||
                        (x.WorkOrderProductName != null && x.WorkOrderProductName.Contains(request.ProductName))).ToList();
                }
                
                if (!string.IsNullOrEmpty(request.Status))
                {
                    joinQueryData = joinQueryData.Where(x => x.WorkOrderStatus == request.Status).ToList();
                }

                if (request.PlannedStartDate.HasValue)
                {
                    joinQueryData = joinQueryData.Where(x => x.PlannedStartTime >= request.PlannedStartDate.Value).ToList();
                }

                if (request.PlannedEndDate.HasValue)
                {
                    joinQueryData = joinQueryData.Where(x => x.PlannedEndTime <= request.PlannedEndDate.Value.AddDays(1)).ToList();
                }

                // 根据报工表的Producer字段筛选创建人
                if (!string.IsNullOrEmpty(request.CreateBy))
                {
                    joinQueryData = joinQueryData.Where(x => 
                        (x.WorkReportProducer != null && x.WorkReportProducer.Contains(request.CreateBy)) ||
                        (x.RelationCreateBy != null && x.RelationCreateBy.Contains(request.CreateBy))).ToList();
                }

                // 转换为DTO - 主要使用报工表数据，只从工单表获取工单编号
                var dtoList = joinQueryData.Select(item => new WorkOrderReportViewDto
                {
                    Id = item.WorkReportId ?? 0, // 使用报工ID作为主ID
                    RelationId = item.RelationId, // 使用真实的中间表ID
                    WorkOrderId = item.WorkOrderId,
                    WorkOrderCode = item.WorkOrderCode, // 从工单表获取工单编号
                    WorkReportId = item.WorkReportId ?? 0,
                    
                    // 产品信息优先使用报工表，如果报工表没有则使用工单表
                    ProductCode = item.WorkReportProductCode ?? item.WorkOrderProductCode,
                    ProductName = item.WorkReportProductName ?? item.WorkOrderProductName,
                    Unit = item.WorkReportUnit ?? item.WorkOrderUnit,
                    Spec = item.WorkReportProductSpec,
                    
                    // 状态和计划信息从工单表获取
                    Status = item.WorkOrderStatus,
                    PlannedStartTime = item.PlannedStartTime,
                    PlannedEndTime = item.PlannedEndTime,
                    PlannedQuantity = item.PlannedQuantity,
                    ActualQuantity = item.ActualQuantity,
                    
                    // 报工相关数据优先使用报工表
                    GoodQuantity = item.WorkReportGoodQty ?? item.WorkOrderGoodQuantity ?? 0,
                    BadQuantity = item.WorkReportDefectiveQty ?? item.WorkOrderBadQuantity ?? 0,
                    ReportHours = item.ReportHours ?? 0m,
                    Progress = item.ProcessProgress,
                    
                    // 备注和时间信息
                    Remark = item.RelationRemark ?? item.WorkOrderRemark,
                    CreateTime = item.WorkReportCreateTime ?? item.RelationCreateTime, // 优先使用报工时间
                    CreateBy = item.WorkReportProducer ?? item.RelationCreateBy ?? item.WorkOrderCreateBy,
                    UpdateBy = item.RelationUpdateBy ?? item.WorkOrderUpdateBy,
                    UpdateTime = item.RelationUpdateTime ?? item.WorkOrderUpdateTime
                }).ToList();

                // 计算总数
                var totalCount = dtoList.Count;

                // 应用排序和分页
                var sortedData = ApplySorting(dtoList, request.SortField, request.SortOrder);
                var pagedData = sortedData
                    .Skip((request.Index - 1) * request.Size)
                    .Take(request.Size)
                    .ToList();

                // 关联工序列表（按页加载，避免一次性加载全部）
                var pagedWorkOrderIds = pagedData
                    .Where(x => x.WorkOrderId > 0)
                    .Select(x => x.WorkOrderId)
                    .Distinct()
                    .ToList();

                if (pagedWorkOrderIds.Count > 0)
                {
                    var processes = await _workOrderProcessRepo
                        .GetAll()
                        .Where(p => pagedWorkOrderIds.Contains(p.WorkOrderId))
                        .OrderBy(p => p.Sequence)
                        .ToListAsync();

                    var processLookup = processes
                        .GroupBy(p => p.WorkOrderId)
                        .ToDictionary(
                            g => g.Key,
                            g => g.Select(p => new WorkOrderProcessBriefDto
                            {
                                Id = p.Id,
                                WorkOrderId = p.WorkOrderId,
                                Sequence = p.Sequence,
                                ProcessCode = p.ProcessCode,
                                ProcessName = p.ProcessName,
                                PlannedQuantity = p.PlannedQuantity,
                                ReportedQuantity = p.ReportedQuantity,
                                GoodQuantity = p.GoodQuantity,
                                BadQuantity = p.BadQuantity,
                                Status = p.Status
                            }).ToList()
                        );

                    foreach (var dto in pagedData)
                    {
                        if (dto.WorkOrderId > 0 && processLookup.TryGetValue(dto.WorkOrderId, out var list))
                        {
                            dto.Processes = list;
                        }
                    }
                }

                _logger.LogInformation($"查询完成，共 {totalCount} 条记录，返回 {pagedData.Count} 条");

                // 计算总页数
                var totalPages = (int)Math.Ceiling((double)totalCount / request.Size);
                
                return new ApiPageing<WorkOrderReportViewDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "获取成功",
                    TotaCount = totalCount,
                    TotaPage = totalPages,
                    PageData = pagedData
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"查询工单报工关联列表失败：{ex.Message}");
                
                return new ApiPageing<WorkOrderReportViewDto>
                {
                    Code = ApiEnum.Fail,
                    Msg = $"查询失败：{ex.Message}",
                    TotaCount = 0,
                    TotaPage = 0,
                    PageData = new List<WorkOrderReportViewDto>()
                };
            }
        }

        /// <summary>
        /// 应用排序逻辑 - 针对List集合
        /// </summary>
        private List<WorkOrderReportViewDto> ApplySorting(List<WorkOrderReportViewDto> list, string? sortField, string? sortOrder)
        {
            if (string.IsNullOrEmpty(sortField))
                return list.OrderByDescending(x => x.CreateTime).ToList();

            var isDescending = !string.IsNullOrEmpty(sortOrder) && sortOrder.ToLower() == "desc";

            return sortField.ToLower() switch
            {
                "workordercode" => isDescending ? list.OrderByDescending(x => x.WorkOrderCode).ToList() : list.OrderBy(x => x.WorkOrderCode).ToList(),
                "productcode" => isDescending ? list.OrderByDescending(x => x.ProductCode).ToList() : list.OrderBy(x => x.ProductCode).ToList(),
                "productname" => isDescending ? list.OrderByDescending(x => x.ProductName).ToList() : list.OrderBy(x => x.ProductName).ToList(),
                "status" => isDescending ? list.OrderByDescending(x => x.Status).ToList() : list.OrderBy(x => x.Status).ToList(),
                "plannedstarttime" => isDescending ? list.OrderByDescending(x => x.PlannedStartTime).ToList() : list.OrderBy(x => x.PlannedStartTime).ToList(),
                "plannedendtime" => isDescending ? list.OrderByDescending(x => x.PlannedEndTime).ToList() : list.OrderBy(x => x.PlannedEndTime).ToList(),
                "actualquantity" => isDescending ? list.OrderByDescending(x => x.ActualQuantity).ToList() : list.OrderBy(x => x.ActualQuantity).ToList(),
                "reporthours" => isDescending ? list.OrderByDescending(x => x.ReportHours).ToList() : list.OrderBy(x => x.ReportHours).ToList(),
                "createtime" => isDescending ? list.OrderByDescending(x => x.CreateTime).ToList() : list.OrderBy(x => x.CreateTime).ToList(),
                _ => list.OrderByDescending(x => x.CreateTime).ToList()
            };
        }
    }
}
